package com.hilin.common.common.handler;

import com.hilin.common.common.ReturnCode;
import com.hilin.common.util.AssertUtils;
import com.hilin.entity.anno.NoToken;
import com.hilin.entity.vo.SignVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.ObjectUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
public class RequestTokenHandler implements HandlerInterceptor {

    private static final Map<Integer, Boolean> METHOD_CACHE = new ConcurrentHashMap<>();

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        int hashCode = handler.hashCode();
        Boolean needToken = METHOD_CACHE.get(hashCode);

        if (needToken == null || needToken) {
            return checkToken(request, handler, hashCode);
        }
        return true;
    }

    public boolean checkToken(HttpServletRequest request, Object handler, int hashCode) {
        String token = request.getHeader("token");

        if (!(handler instanceof HandlerMethod)) {
            return true;
        }
        HandlerMethod handlerMethod = (HandlerMethod) handler;

        NoToken noToken = handlerMethod.getMethodAnnotation(NoToken.class);
        // 是否无需token认证
        if (!ObjectUtils.isEmpty(noToken)) {
            METHOD_CACHE.put(hashCode, false);
            return true;
        }

        String uri = request.getRequestURI();

        // 判断是否是swagger接口
        if (!ObjectUtils.isEmpty(uri) &&
                (uri.contains("api-docs") || uri.contains("swagger"))) {
            // 登录接口无需验证，直接访问
            METHOD_CACHE.put(hashCode, false);
            return true;
        }

        // token是否为空
        AssertUtils.isNotEmpty(token, ReturnCode.AUTH_ERROR.respMsg("token为空"));

        // FixME  获取签名信息
        SignVo signVo = null;
//        accountInfoPoRedisTemplate.opsForValue().get(String.format(RedisKeys.RK_USER_TOKEN, token));
        // token是否可用
        AssertUtils.isNotEmpty(signVo, ReturnCode.AUTH_ERROR.respMsg("token无效"));

        request.setAttribute("userInfo", signVo);
        METHOD_CACHE.put(hashCode, true);
        return true;
    }

}
